using Infrastructure.Attribute;
using Infrastructure.Extensions;
using ZR.Model.ProdManage.Dto;
using ZR.Model.ProdManage;
using ZR.Repository;
using ZR.Service.ProdManage.IProdManageService;
using Infrastructure;
using System.Threading.Tasks;

namespace ZR.Service.ProdManage
{
    /// <summary>
    /// bom信息Service业务层处理
    /// </summary>
    [AppService(ServiceType = typeof(IProdBomService), ServiceLifetime = LifeTime.Transient)]
    public class ProdBomService : BaseService<ProdBom>, IProdBomService
    {
        /// <summary>
        /// 查询bom信息列表
        /// </summary>
        /// <param name="parm"></param>
        /// <returns></returns>
        public PagedInfo<ProdBomDto> GetPageList(ProdBomQueryDto parm)
        {
            var predicate = QueryExp(parm);

            var response = Queryable()
                .Where(predicate.ToExpression())
                .ToPage<ProdBom, ProdBomDto>(parm);

            return response;
        }


        /// <summary>
        /// 获取详情
        /// </summary>
        /// <param name="BomId"></param>
        /// <returns></returns>
        public ProdBom GetInfo(string BomId)
        {
            var response = Queryable()
                .Where(x => x.BomId == BomId)
                .First();

            return response;
        }

        /// <summary>
        /// 添加bom信息
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public ProdBom AddProdBom(ProdBom model)
        {
            return Insertable(model).ExecuteReturnEntity();
        }

        /// <summary>
        /// 修改bom信息
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public int UpdateProdBom(ProdBom model)
        {
            return Update(model, true);
        }

        /// <summary>
        /// 导入bom信息
        /// </summary>
        /// <returns></returns>
        public (string, object, object) ImportProdBom(List<ProdBom> list)
        {
            var x = Context.Storageable(list)
                .SplitInsert(it => !it.Any())
                .SplitError(x => x.Item.BomId.IsEmpty(), "bom主键不能为空")
                .SplitError(x => x.Item.ItemNo.IsEmpty(), "产品编号不能为空")
                .SplitError(x => x.Item.ItemType.IsEmpty(), "产品类型不能为空")
                .SplitError(x => x.Item.PartCode.IsEmpty(), "零件号不能为空")
                .SplitError(x => x.Item.Qty.IsEmpty(), "用量不能为空")
                .SplitError(x => x.Item.IsFill.IsEmpty(), "是否填充(0=否,1=是)不能为空")

                .ToStorage();
            x.AsInsertable.ExecuteCommand();//插入可插入部分;

            string msg = $"插入{x.InsertList.Count} 更新{x.UpdateList.Count} 错误数据{x.ErrorList.Count} 不计算数据{x.IgnoreList.Count} 删除数据{x.DeleteList.Count} 总共{x.TotalList.Count}";
            Console.WriteLine(msg);

            return (msg, x.ErrorList, x.IgnoreList);
        }

        /// <summary>
        /// 导出bom信息
        /// </summary>
        /// <param name="parm"></param>
        /// <returns></returns>
        public PagedInfo<ProdBomDto> ExportList(ProdBomQueryDto parm)
        {
            var predicate = QueryExp(parm);

            var response = Queryable()
               .Where(predicate.ToExpression())
               .Select((it) => new ProdBomDto()
               {
               }, true)
               .ToPage(parm);

            return response;
        }

        /// <summary>
        /// 查询导出表达式
        /// </summary>
        /// <param name="parm"></param>
        /// <returns></returns>
        private static Expressionable<ProdBom> QueryExp(ProdBomQueryDto parm)
        {
            var predicate = Expressionable.Create<ProdBom>();

            predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.ItemNo), it => it.ItemNo == parm.ItemNo);
            predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.PartCode), it => it.PartCode == parm.PartCode);
            predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.IsFill), it => it.IsFill == parm.IsFill);
            predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.DmsOrderNo), it => it.DmsOrderNo == parm.DmsOrderNo);
            predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.PlanNo), it => it.PlanNo == parm.PlanNo);
            return predicate;
        }

        /// <summary>
        /// 生产bom推送
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        public async Task<bool> CogradientProdBom(List<WmsBomDto> list)
        {
            if (list == null || list.Count == 0) throw new CustomException("推送的bom信息为空");

            //判断是否已经推送计划
            List<string> codes = list.Select(x => x.planNo).Distinct().ToList();
            List<ProdBom> oldList = Queryable().Where(it => codes.Contains(it.PlanNo)).ToList();

            List<ProdBom> addList = new List<ProdBom>();
            foreach (var item in list)
            {
                if (oldList.Any(it => it.PartCode == item.partCode && it.ItemNo == item.itemNo)) continue;
                ProdBom bom = new ProdBom()
                {
                    BomId = Guid.NewGuid().ToString().ToUpper(),
                    PlanNo = item.planNo,
                    DmsOrderNo = item.dmsOrderNo,
                    ItemNo = item.itemNo,
                    ItemType = item.itemType,
                    PartCode = item.partCode,
                    Qty = item.qty,
                    ChangeNo = item.changeNo,
                    WareCode = item.wareCode,
                    EffectDate = item.effectDate,
                    ExpirationDate = item.expirationDate,
                    IsFill = item.isFill,
                    ObtainType = item.obtainType,
                    CreateUser = item.createUser,
                    SupplierCode = item.supplierCode,
                    CreateBy = "wms",
                    CreateTime = DateTime.Now,
                };
                addList.Add(bom);
            }

            //执行事务
            var db = this.Context.Ado;
            var res = await db.UseTranAsync(async () =>
            {
                if (addList.Count > 0)
                {
                    await db.Context.Insertable(addList).ExecuteCommandAsync();
                }
                return true;
            });
            if (res.Data == false)
            {
                throw new CustomException(res.ErrorMessage);
            }

            return true;
        }
    }
}